package easyexcel

import (
	"github.com/xuri/excelize/v2"
	"io"
	"net/http"
	"strconv"
	"time"
)

type WriteExcel[T any] interface {

	// SheetName 配置工作簿名称
	SheetName(sheetName string) WriteExcel[T]

	// TimeFormat 配置时间格式化
	TimeFormat(timeFormat string) WriteExcel[T]

	// ColWidthConfig 列宽设置配置
	ColWidthConfig(startCol, endCol string, width float64) WriteExcel[T]

	// RowHeight 行高设置配置
	RowHeight(height float64) WriteExcel[T]

	// WriteLocal 数据写入excel，并保存到本地
	WriteLocal(fileName string, beans []T)

	// WriteResponse 数据写入excel，并输出到浏览器
	WriteResponse(response http.ResponseWriter, beans []T)

	// WriteNet 数据写入excel，并输出到网络中
	WriteNet(writer io.Writer, beans []T)
}

type beanToExcel[T any] struct {
	*easyExcel[T]
}

// SheetName 配置sheet name
func (te *beanToExcel[T]) SheetName(sheetName string) WriteExcel[T] {
	te.setSheetName(sheetName)
	return te
}

// TimeFormat 配置时间格式化
func (te *beanToExcel[T]) TimeFormat(timeFormat string) WriteExcel[T] {
	te.setTimeFormat(timeFormat)
	return te
}

// ColWidthConfig 列宽设置配置
func (te *beanToExcel[T]) ColWidthConfig(startCol, endCol string, width float64) WriteExcel[T] {
	te.setColWidthConfig(startCol, endCol, width)
	return te
}

// RowHeight 行高设置配置
func (te *beanToExcel[T]) RowHeight(height float64) WriteExcel[T] {
	te.setRowHeight(height)
	return te
}

// WriteLocal 数据写入excel，并保存到本地
func (te *beanToExcel[T]) WriteLocal(fileName string, beans []T) {
	if fileName == "" {
		panic("excel文件名不能为空")
	}

	file := te.write(beans)
	defer func() {
		if err := file.Close(); err != nil {
			panic(err)
		}
	}()

	// 根据指定路径保存文件
	if err := file.SaveAs(fileName); err != nil {
		panic(err)
	}
}

// WriteResponse 数据写入excel到浏览器
func (te *beanToExcel[T]) WriteResponse(response http.ResponseWriter, beans []T) {
	milliStr := strconv.FormatInt(time.Now().UnixMilli(), 10)
	response.Header().Set("Content-Disposition", "attachment; filename="+milliStr+".xlsx")
	response.Header().Set("Content-Type", "application/octet-stream")
	te.WriteNet(response, beans)
}

func (te *beanToExcel[T]) WriteNet(writer io.Writer, beans []T) {
	if writer == nil {
		panic("writer must not be nil")
	}

	if len(beans) <= 0 {
		panic("数据为空")
	}

	file := te.write(beans)
	defer func() {
		if err := file.Close(); err != nil {
			panic(err)
		}
	}()

	err := file.Write(writer)
	if err != nil {
		panic(err)
	}
}

func (te *beanToExcel[T]) write(beans []T) *excelize.File {
	file := excelize.NewFile()
	// 创建一个工作表
	index, err := file.NewSheet(te.sheetName)
	if err != nil {
		panic(err)
	}

	// 配置设置
	te.settingFile(file)

	// 设置单元格的表头
	err = file.SetSheetRow(te.sheetName, "A1", &te.tagTitles)
	if err != nil {
		panic(err)
	}

	// 设置单元格的值
	for i, bean := range beans {
		cell := "A" + strconv.Itoa(i+2)
		rows := te.bean2Rows(file, bean, i+2)
		err = file.SetSheetRow(te.sheetName, cell, &rows)
		if err != nil {
			panic(err)
		}
	}

	// 设置工作簿的默认工作表
	file.SetActiveSheet(index)
	return file
}
